package com.thunbu.thunbu_meeting_system

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.MotionEvent.*
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import androidx.lifecycle.*
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.BaseViewHolder
import com.google.gson.Gson
import com.hjq.toast.ToastUtils
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.impl.LoadingPopupView
import com.thunbu.lib_common.config.BaseResponse
import com.thunbu.lib_common.utils.ActivityManager
import com.thunbu.lib_common.utils.kick.KickInfo
import com.thunbu.lib_common.utils.kick.LogoutMonitor
import com.thunbu.thunbu_meeting_system.service.NetErrorCode
import kotlinx.coroutines.*
import okhttp3.MediaType
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException


/**
 *Created by Chaolue.Fan on 2021/5/14
描述:
 */

/**
 * 跳转
 */
inline fun <reified T : Activity> Activity.gotoActivity(noinline params: (Intent.() -> Unit)? = null) {
    startActivity(Intent(this, T::class.java).apply {
        params?.let {
            it()
        }
    })
}


fun View.clickColorStates(action: MotionEvent, alphaDown: Float = 0.7f) {
    when (action.action) {
        ACTION_DOWN -> {
            Log.i("fancl", "ACTION_DOWN")
            alpha = alphaDown
        }
        ACTION_UP -> {
            Log.i("fancl", "ACTION_UP")
            alpha = 1f
        }
        ACTION_CANCEL -> {
            Log.i("fancl", "ACTION_CANCEL")
        }

    }
}


/**
 * <让 View 在 @param time 内不可点击>
 */
fun View.sleep(time: Long = 1000) {
    this.isEnabled = false
    launch({
        delay(time)
        this.isEnabled = true
    })
}

inline fun View.avoidClick() {
    val listenerInfo =
        View::class.java.getDeclaredMethod("getListenerInfo").apply { isAccessible = true }
            .invoke(this)
    val clickListener = listenerInfo::class.java.getField("mOnClickListener").get(listenerInfo)
    if (clickListener == null) {
        throw IllegalStateException("该方法必须在设置 onClickListener 之后")
    } else {
        val clickListenerProxy = View.OnClickListener {
            clickListener::class.java.getMethod("onClick", View::class.java)
                .invoke(clickListener, this@avoidClick)
            this.sleep()
        }
        listenerInfo::class.java.getField("mOnClickListener").set(listenerInfo, clickListenerProxy)
    }
}


fun toast(str: String) {
    ToastUtils.show(str)
}


fun toast(@StringRes str: Int) {
    ToastUtils.show(str)
}


/**
 * 默认主线程的协程
 */
fun launch(
        block: suspend (CoroutineScope) -> Unit,
        error_: ((e: Throwable) -> Unit)? = null,
        context: CoroutineContext = Dispatchers.Main,
) = GlobalScope.launch(context + CoroutineExceptionHandler { _, e ->
    Log.e("==>coroutineException", e.message + "\n" + Log.getStackTraceString(e))
    error_?.let { it(e) }
}) {
    try {
        block(this)
    } catch (e: Exception) {
        Log.e("==>coroutineError", e.message + "\n" + Log.getStackTraceString(e))
        error_?.let { it(e) }
    }
}


/**
 * 默认主线程的协程
 * 添加生命周期管理
 */
fun launchWithLife(
        life: LifecycleOwner?,
        block: suspend (CoroutineScope) -> Unit,
        error_: ((e: Throwable) -> Unit)? = null,
        context: CoroutineContext = Dispatchers.Main,
) {
    val job = launch(block, error_, context)

    life?.lifecycle?.addObserver(object : LifecycleEventObserver {
        override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
            if (life.lifecycle.currentState == Lifecycle.State.DESTROYED) {
                job.cancel("the lifecycleOwner(${life.javaClass.simpleName}) has been destroyed")
                return;
            }
        }
    })
}


/**
 *  <自控生命周期>
 */
fun <T> LiveData<T>.observeLife(
        life: LifecycleOwner,
        minState: Lifecycle.State = Lifecycle.State.DESTROYED,
        observer: Observer<T>,
) {
    this.observeForever(observer)
    life.lifecycle.addObserver(object : LifecycleEventObserver {
        override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
            if (life.lifecycle.currentState == minState) {
                this@observeLife.removeObserver(observer)
                life.lifecycle.removeObserver(this)
                return
            }
        }
    })
}

/**
 * 包含数字和字母
 */
fun isLetterDigit(str: String): Boolean {

    var isDigit = false
    var isLetter = false
    str.toList().forEach {
        if (Character.isDigit(it))
            isDigit = true
        if (Character.isLetter(it))
            isLetter = true
    }

    return isDigit && isLetter
}

fun Fragment.hideKeyboard(){
    val imm: InputMethodManager =
        context!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
    // 隐藏软键盘
    imm.hideSoftInputFromWindow(activity?.getWindow()?.getDecorView()?.getWindowToken(), 0)

}

suspend fun <T> Call<T>.await(needShowLoadingDialog: Boolean = false, needErrorToast: Boolean = false, needResponseCode: Boolean = false): T {
    var loadingPopupView:LoadingPopupView? = null
    if(needShowLoadingDialog){
        loadingPopupView = XPopup.Builder(ActivityManager.instance.getTopActivity()).asLoading()
        loadingPopupView.show()
    }
    return suspendCancellableCoroutine { continuation ->

        continuation.invokeOnCancellation {
            cancel()
            if (needShowLoadingDialog) loadingPopupView?.dismiss()
        }

        enqueue(object : Callback<T> {
            override fun onResponse(call: Call<T>, response: Response<T>) {
                if (needShowLoadingDialog) loadingPopupView?.dismiss()
                if (response.isSuccessful) {
                    if (response.body() != null) {
                        val t = response.body() as T
                        //是BaseResponse的直接解析,不是的,单独解析
                        if (t is BaseResponse<*> ) {
                            //token失效
                            if (t.code == NetErrorCode.CODE_TOKEN_INVALID) {
                                LogoutMonitor.getInstance().emitter(KickInfo(KickInfo.REASON.COOKIE_INVALID))
                                onFailure(call, Throwable())
                                return
                            }
                            if(needResponseCode || t.isSuccess){
                                continuation.resume(t)
                            } else {
                                onFailure(call, Throwable(t.message))
                            }
                        } else {
                            continuation.resume(t)
                        }
                    } else {
                        onFailure(call, Throwable("body 为空"))
                    }
                } else {
                    onFailure(call, Throwable("网络异常"))
                }
            }

            override fun onFailure(call: Call<T>, t: Throwable) {
                Log.e("==>Call", "onFailure${t.message}")
                if (needErrorToast) ToastUtils.show(t.message)
                if (needShowLoadingDialog) loadingPopupView?.dismiss()
                continuation.resumeWithException(
                        IllegalStateException(
                                "网络异常"
                        )
                )
            }
        })
    }
}

/**
 *  <三目运算符>
 */
inline fun <T> Boolean.ternary(trueValue: T, falseValue: T): T {
    return if (this) {
        trueValue
    } else {
        falseValue
    }
}

fun Map<*, *>.toRequestBody() =
    RequestBody.create(MediaType.parse("application/json"), Gson().toJson(this))


inline fun <reified VB : ViewBinding, T> RecyclerView.bindAdapter(crossinline block: VB.(item: T, position: Int) -> Unit): BaseVBQuickAdapter<T, VB>{
    val adapter = object : BaseVBQuickAdapter<T, VB>(){
        override fun convert(helper: BaseVBViewHolder<VB>, item: T) {
            helper.binding.apply {
//                block(item,helper.adapterPosition)
                block(item, data.indexOf(item))
            }
        }

        override fun createBaseViewHolder(parent: ViewGroup, layoutResId: Int): BaseVBViewHolder<VB> {
            val method = VB::class.java.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
            val binding = method.invoke(null, mLayoutInflater, parent, false) as VB
            return  BaseVBViewHolder(binding)
        }
    }
    this.adapter = adapter
    return adapter
}



abstract class BaseVBQuickAdapter<T, VB : ViewBinding>: BaseQuickAdapter<T, BaseVBViewHolder<VB>>(0)

class BaseVBViewHolder<VB : ViewBinding>(val binding: VB) : BaseViewHolder(binding.root)
